﻿#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //滑块的设定
    const int a=75;
    const int b=100;
    const int side=100;

    N = 9;//滑块个数
    int sqn = sqrt(N);
    //存储序号
    p=generate(N);
    //滑块就是按钮
    Block = new QPushButton[N];
    for(int i=0;i<sqn;i++){
        for(int j=0;j<sqn;j++){
            //将按钮控件添加到当前的窗口中
            Block[sqn*i+j].setParent(this);
            Block[sqn*i+j].setFont(QFont("HGB8X_CNKI",18));
            Block[sqn*i+j].setStyleSheet("background-image: url(:/Image/resource/blockImg.jpg);");
            Block[sqn*i+j].setFocusPolicy(Qt::NoFocus);//NoFocus

            //(左边缘，上边缘，宽，高)设置大小
            Block[sqn*i+j].setGeometry(a+side*j,b+side*i,side,side);
            //信号与槽函数
            connect(&Block[sqn*i+j],&QPushButton::clicked,this,[=](){
                this->update(i,j);
            });
            if(!(i == sqn-1 && j == sqn-1))
                Block[sqn*i+j].setText(QString::number(p[sqn*i+j]));
        }
    }
    Void = new Coordinate(sqn);//存储空滑块下标

    //记步数
    step = new QLabel(this);
    step->setGeometry(600,200,400,50);
    step->setText("Steps:  "+QString::number(totalSteps));
    step->setFont(QFont("宋体",18,QFont::Bold,true));

    //记时间
    time = new QLabel(this);
    time->setGeometry(600,300,400,50);
    time->setText("Time:   "+QString::number(0));
    time->setFont(QFont("宋体",18,QFont::Bold,true));
    timer = new QTimer(this);
    connect(timer,&QTimer::timeout,this,&MainWindow::timeoutShow);
    //准备开始计时工作
    isBegin = false;
    startTime = new QDateTime;//先分配内存

    //进行计算机自动移动模块
    //转换界面的按钮
    computer_player = new QPushButton(this);
    computer_player->setGeometry(600,400,150,50);
    computer_player->setText("计算机移动");
    computer_player->setFont(QFont("方正楷体",14));
    computer_player->setStyleSheet("border: 4px inset rgb(255,255,255);""border-radius:10px;");
    computer_player->setFocusPolicy(Qt::NoFocus);//NoFocus
    connect(computer_player,&QPushButton::clicked,this,&MainWindow::creat);
    connect(computer_player,&QPushButton::clicked,this,&MainWindow::hide);

    //重新开始的模块
    QPushButton* restart = new QPushButton(this);
    restart->setGeometry(600,470,150,50);
    restart->setText("重新开始");
    restart->setFont(QFont("方正楷体",14));
    connect(restart,&QPushButton::clicked,this,&MainWindow::restartGame);
    restart->setStyleSheet("border: 4px inset rgb(255,255,255);""border-radius:10px;");
    restart->setFocusPolicy(Qt::NoFocus);//NoFocus

    //难度选择
    QPushButton *levelb = new QPushButton(this);
    levelb->setGeometry(600,540,150,50);
    levelb->setText("难度选择");
    levelb->setFont(QFont("方正楷体",14));
    //设置边框
    levelb->setStyleSheet("border: 4px inset rgb(255,255,255);""border-radius:10px;");
    levelb->setFocusPolicy(Qt::NoFocus);//NoFocus
    level* levelWindow = new level(nullptr);//必须是nullptr
    connect(levelb,&QPushButton::clicked,levelWindow,&level::show);
    connect(levelb,&QPushButton::clicked,this,&MainWindow::hide);
    connect(levelWindow->easyLevel,&QPushButton::clicked,this,[&](){
        this->restartGame(3);
    });
    connect(levelWindow->easyLevel,&QPushButton::clicked,this,&MainWindow::show);
    connect(levelWindow->normalLevel,&QPushButton::clicked,this,[&](){
        this->restartGame(4);
    });
    connect(levelWindow->normalLevel,&QPushButton::clicked,this,&MainWindow::show);
    connect(levelWindow->crazyLevel,&QPushButton::clicked,this,[&](){
        this->restartGame(5);
    });
    connect(levelWindow->crazyLevel,&QPushButton::clicked,this,&MainWindow::show);
    //返回按钮
    connect(levelWindow->backGame,&QPushButton::clicked,this,&MainWindow::show);

    //添加背景
    QImage *backImg = new QImage();
    backImg->load(":/Image/resource/backImg.png");
    QLabel *back = new QLabel(this);
    back->setFixedSize(1000,650);
    back->setPixmap(QPixmap::fromImage(*backImg));
    back->lower();
    //添加滑块音效
    blockAudio = new QSound(":/sound/resource/BlockAudio.wav");
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::creat(){
     computer *computerWindow = new computer(nullptr);
     computerWindow->layoutbutton(p,N);
     computerWindow->show();
     connect(computerWindow->backgame,&QPushButton::clicked,computerWindow,&computer::close);
     connect(computerWindow->backgame,&QPushButton::clicked,this,&MainWindow::show);
}
void MainWindow::restartGame(int X){
    //从0开始
    timer->stop();
    totalSteps = 0;
    int sqn = sqrt(N);
    isBegin = false;
    step->setText("Steps:  "+QString::number(totalSteps));
    time->setText("Time:   "+QString::number(0));
    if(X == 0){
        p = generate(N);
        for(int i=0;i<sqrt(N);i++){
            for(int j=0;j<sqrt(N);j++){
                Block[(int)(sqrt(N))*i+j].setFocusPolicy(Qt::NoFocus);//NoFocus
                Block[sqn*i+j].setFont(QFont("HGB8X_CNKI",18));
                Block[sqn*i+j].setStyleSheet("background-image: url(:/Image/resource/blockImg.jpg);");
                Block[sqn*i+j].setFocusPolicy(Qt::NoFocus);//NoFocus
                if(!(i == sqrt(N)-1 && j == sqrt(N)-1))
                    Block[(int)(sqrt(N))*i+j].setText(QString::number(p[(int)(sqrt(N))*i+j]));
                else
                    Block[(int)(sqrt(N))*i+j].setText("");
            }
        }
        Void->setIndex(sqrt(N)-1,sqrt(N)-1);
        return;
    }
    else{
        N = X*X;
        int a;
        int b;
        int side;
        switch(X){
        case 3:
            a = 100;
            b = 100;
            side = 125;
            break;
        case 4:
            a = 75;
            b = 100;
            side = 100;
            break;
        case 5:
            a = 30;
            b = 50;
            side = 100;
            break;
        }
        p = generate(N);
        delete[] Block;//回收
        Block = new QPushButton[N];
        for(int i=0;i<sqrt(N);i++){
            for(int j=0;j<sqrt(N);j++){
                Block[(int)(sqrt(N))*i+j].setParent(this);
                Block[(int)(sqrt(N))*i+j].setGeometry(a+side*j,b+side*i,side,side);
                connect(&Block[(int)(sqrt(N))*i+j],&QPushButton::clicked,this,[=](){
                    this->update(i,j);
                });
                Block[(int)(sqrt(N))*i+j].setFont(QFont("HGB8X_CNKI",18));
                Block[(int)(sqrt(N)*i+j)].setStyleSheet("background-image: url(:/Image/resource/blockImg.jpg);");
                Block[(int)(sqrt(N))*i+j].setFocusPolicy(Qt::NoFocus);//NoFocus
                if(!(i == sqrt(N)-1 && j == sqrt(N)-1))
                    Block[(int)(sqrt(N))*i+j].setText(QString::number(p[(int)(sqrt(N))*i+j]));
            }
        }
        delete[] Void;
        Void = new Coordinate(sqrt(N));
        return;
    }
}
//更新
int* MainWindow::generate(int N){
    int *p = new int[N-1];
    for(int i=0;i<N-1;i++)
        p[i]=i+1;
    while(true){
        std::mt19937 generator(std::time(nullptr));//生成随机数种子
        std::shuffle(p, p + N - 1, generator);
        int count = 0;
        for(int i=0;i<N-1;++i){
            for(int j=i+1;j<N-1;++j){
                if(*(p+i)>*(p+j)){
                    count++;
                }
            }
        }
        if(count%2==0){
            break;
        }
    }
    return p;
}
void MainWindow::update(int a, int b)
{
    //相邻滑块坐标
    Coordinate *Up = new Coordinate(Void->X()-1,Void->Y(),sqrt(Void->N()));
    Coordinate *Down = new Coordinate(Void->X()+1,Void->Y(),sqrt(Void->N()));
    Coordinate *Left = new Coordinate(Void->X(),Void->Y()-1,sqrt(Void->N()));
    Coordinate *Right = new Coordinate(Void->X(),Void->Y()+1,sqrt(Void->N()));

    //转化到一维数组下的下标
    int n = sqrt(Void->N()) * a + b; //被点击滑块的 单 坐标

    if(n==Up->retIndex()){
        Block[Void->retIndex()].setText(Block[Up->retIndex()].text());
        Block[Up->retIndex()].setText("");
        Void->setIndex(Up->X(),Up->Y());
        blockAudio->play();
        totalSteps++;
        step->setText("Steps:  "+QString::number(totalSteps));
        if(!isBegin){
            timer->start();
            *startTime = QDateTime::currentDateTime();
            isBegin = true;
        }
        //更新窗口
        QWidget::update();
    }
    if(n==Down->retIndex()){
        Block[Void->retIndex()].setText(Block[Down->retIndex()].text());
        Block[Down->retIndex()].setText("");
        Void->setIndex(Down->X(),Down->Y());
        blockAudio->play();
        totalSteps++;
        step->setText("Steps:  "+QString::number(totalSteps));
        if(!isBegin){
            timer->start();
            *startTime = QDateTime::currentDateTime();
            isBegin = true;
        }
        QWidget::update();
    }
    if(n==Left->retIndex()){
        Block[Void->retIndex()].setText(Block[Left->retIndex()].text());
        Block[Left->retIndex()].setText("");
        Void->setIndex(Left->X(),Left->Y());
        blockAudio->play();
        totalSteps++;
        step->setText("Steps:  "+QString::number(totalSteps));
        if(!isBegin){
            timer->start();
            *startTime = QDateTime::currentDateTime();
            isBegin = true;
        }
        QWidget::update();
    }
    if(n==Right->retIndex()){
        Block[Void->retIndex()].setText(Block[Right->retIndex()].text());
        Block[Right->retIndex()].setText("");
        Void->setIndex(Right->X(),Right->Y());
        blockAudio->play();
        totalSteps++;
        step->setText("Steps:  "+QString::number(totalSteps));
        if(!isBegin){
            timer->start();
            *startTime = QDateTime::currentDateTime();
            isBegin = true;
        }
        QWidget::update();
    }
    //判断游戏结束
    bool isOver = true;
    for(int i=0;i<Void->N()-1;i++){//除去最后一个滑块
        if(Block[i].text()!=QString::number(i+1)){
            isOver = false;
            break;
        }
    }
    if(isOver){
        timer->stop();
        QMessageBox overWindow;
        overWindow.setText("恭喜你！(≧∇≦)/你赢了~\n总步数："+QString::number(totalSteps));
        overWindow.setWindowTitle("游戏胜利(^o^)");
        overWindow.setFixedSize(100,65);
        overWindow.exec();
    }
}

void MainWindow::timeoutShow()
{
    QDateTime endTime = QDateTime::currentDateTime();
    long long int interval = startTime->secsTo(endTime);
    time->setText("Time:   "+QString::number(interval)+"s");
}
